<template>
    <div class="dcimSelect">
        <div class="s-header" :title="selected" @click="slideDown">
            <span class="text" v-text="selected"></span>
            <span class="fa-box">
                <i class="fa fa-angle-down"></i>
            </span>
        </div>
        <transition name="slide-fade">
            <div class="s-panel" v-show="on">
                <div class="s-box" :class="[confirm && listData.length > 0 ? 'btn-handle' : '']" @keydown="followMouseCheckList">
                    <!--  搜索 -->
                    <div class="search" :class="reverse && listData.length > 0 ? 'reverse' : ''" v-show="search">
                        <label class="search-panel">
                            <input v-model="searchDataState" />
                        </label>
                        <i class="fa fa-search" @click="searchSelectData"></i>
                        <span class="btn-reverse" @click="reverseCheck" v-show="reverse && listData.length > 0">反选</span>
                    </div>
                    <vue-scroll ref="vs">
                        <ul class="s-list" ref="searchList" :key="resetCode">
                            <template v-if="emptyState">
                                <template v-if="listData.length > 0">
                                    <li
                                            class="list"
                                            :class="[order >= 0 || check ? '' : 'active']"
                                            :data-index="serious"
                                            :data-id="'all'"
                                            v-if="isDefault && haveCheckAll"
                                            @click="checked('all', $event)">
                                        <i class="fa fa-check-square" :class="[checkedAll && !closeSingleChecked ? 'is-checked' : 'fa-square-o']" v-show="check"></i>
                                        <template v-if="!blurState && check && checkCountLimit">&nbsp;前50条数据</template>
                                        <template v-else>{{ defaultText }}</template>
                                    </li>
                                    <li
                                            class="list"
                                            :class="[!isDefault && index === 0 && !defaultSelected || defaultShow && (item.name === defaultSelected  || item.id == defaultSelected) || index === order ? 'active' : '']"
                                            :data-id="item.id"
                                            :data-index="serious"
                                            :data-order="index"
                                            :data-children="item.hasChildren"
                                            :title="item.name"
                                            @click="checked(item.id, $event)"
                                            v-for="(item, index) in listData"
                                            :key="`sl-${ keyId.num }-${ index }`">
                                        <i class="fa fa-check-square" :class="[item.optState ? 'is-checked' : 'fa-square-o']" v-show="check"></i>
                                        {{ item.name }}
                                    </li>
                                </template>
                                <li class="empty" v-else>无匹配结果</li>
                            </template>
                            <loading v-else></loading>
                        </ul>
                    </vue-scroll>
                    <div class="footer" v-if="confirm && listData.length > 0">
                        <el-button type="primary" @click="confirmChecked">确定</el-button>
                    </div>
                </div>
            </div>
        </transition>
        <el-dialog class="dcimToast" width="20%" :visible.sync="toast" append-to-body>选择的数据不能超过50条。</el-dialog>
        <div class="selectMask" v-show="disabled"></div>
    </div>
</template>

<script>
    import { DIALOG } from '../../mixins/dialog'
    export default {
        name: "dcimSelect",
        mixins: [DIALOG],
        props: {
            reverse: { // 反选
                type: Boolean,
                default: false
            },
            checkCountLimit: { //是否限制选择条数
                type: Boolean,
                default: true
            },
            haveCheckAll: { // 是否显示全选
                type: Boolean,
                default: true
            },
            disabled: {
                type: Boolean,
                default: false
            },
            extend: {
                type: Boolean,
                default: () => {
                    return false
                }
            },
            confirm: {
                type: Boolean,
                default: () => {
                    return false
                }
            },
            recoverDefault: {
                type: Object,
                default: () => {
                    return {
                        state: false
                    }
                }
            },
            asyncState: {
                type: Boolean,
                default: () => {
                    return false
                }
            },
            check: {
                type: Boolean,
                default: () => {
                    return false
                }
            },
            search: { // 搜索
                type: Boolean,
                default: () => {
                    return false
                }
            },
            defaultSearch: { // 默认搜索
                type: Boolean,
                default: () => {
                    return false
                }
            },
            keyId: {
                type: [Number, Object],
                default: function () {
                    return {
                        num: 0
                    }
                }
            },
            defaultShow: {
                // 默认选中显示的值，不传默认false
                type: Boolean,
                default: function () {
                    return false;
                }
            },
            defaultSelected: { // 默认选中
                default: function () {
                    return null
                }
            },
            defaultText: { // 初始化默文字
                default: function () {
                    return "全部"
                }
            },
            list: {
                // 下拉列表
                type: Array,
                default: () => {
                    return []
                }
            },
            serious: Number, // 下拉数量，序数列 1,2,3，....
            isDefault: {
                // 是否显示默认文字
                type: Boolean,
                default: () => {
                    return true;
                }
            },
            isFirstNode: { // 是否显示选中的第一个值，通常与isDefault合用，默认显示
                type: Boolean,
                default: () => {
                    return true
                }
            }
        },
        data() {
            return {
                on: false,
                id: "",
                selected: "全部",
                children: [],
                row: [],
                listData: [], // 下拉列表
                defaultListData: [],
                searchDataState: '',
                order: -1,
                checkedAll: false,
                closeSingleChecked: true,
                emptyState: true,
                blurState: true,
                limitFullData: false,
                bindFunc: null,
                resetCode: 0,
                defaultsOpen: false,
            }
        },
        created() {
            const $this = this

            if (!$this.list) return

            if ($this.list.length > 0) {

                $this.extend ? $this.defaultListData = $this.list : $this.defaultListData = $.extend(true, [], $this.list)

                $this.initListData($this.defaultListData)

            }

            document.addEventListener('click', $this.automatismSlideOff , false)

        },
        watch: {
            'recoverDefault.state': function (val) {

                const $this = this

                if ($this.defaultListData.length <= 0) return

                if (val) {

                    $this.resetCode += 1

                    if (!$this.defaultSelected) $this.order = -1

                    if ($this.isDefault) {

                        $this.selected = $this.defaultText

                    } else {

                        $this.selected = $this.defaultListData[0].name

                        $this.defaultSelected ? $this.$emit("selected", $this.defaultListData[0]) : ''

                    }

                    $this.checkedAll = false

                    $this.closeSingleChecked = true

                    $this.listData.map((item) => {

                        item.optState = false

                        item.assetState = true

                    })

                    $this.recoverDefault.state = false

                }
            },
            selected: function (val) {

                if ((val === '请选择' || val === '全部') && !this.check) {

                    this.$emit("selected", '')

                }

            },
            asyncState: function (val) {
                if (!val) {
                    this.emptyState = false
                }
            },
            checkedAll: function (val) {

                const $this = this

                if ($this.closeSingleChecked || !$this.blurState || !$this.check) return

                $this.selected = ''

                $this.listData.map((item) => {

                    item.optState = val

                })

                if (val) {

                    $this.selected = '全部'

                    $this.$emit("selected", $this.listData)

                } else {

                    $this.selected = '请选择'

                    $this.$emit("selected", '')

                }

            },
            // 监听下拉列表的变化，改变默认选中的值
            defaultSelected: function (val) {

                const $this = this

                const data = $this.extend ? $this.list : $.extend(true, [], $this.list)

                let self = []

                $this.order = -1

                data.filter((item, index) => {

                    if (item.id == val || item.name == val) {

                        $this.order = index

                        self = item

                    }

                })

                if (self.length <= 0) return

                $this.selected = self[0] ? self[0].name : self.name

                //页面如果有多个元件未关联资产，如果其他元件关联了资产，那么未关联资产的元件修改时会显示其他元件已关联的设备名称，需要重新赋值
                //$this.searchDataState = $this.selected
            },
            list: function (val) {

                const $this = this

                $this.defaultListData = $this.extend ? val : $.extend(true, [], val)

                $this.initListData($this.defaultListData)

            }
        },
        methods: {
            /**
             * 反选
             */
            reverseCheck() {

                const $this = this

                const checkedData = []
                let selectText = ''

                $this.listData.map((item) => {

                    item.optState = !item.optState

                    if (item.optState) {

                        checkedData.push(item)

                        selectText+=`${item.name},`

                    }

                })

                $this.selected = checkedData.length <= 0 ? '请选择' : selectText.substring(0, selectText.length - 1)

                checkedData.length >= $this.defaultListData.length ?  $this.checkSelectedAll(true, false) : $this.checkSelectedAll(false, true)

                $this.keyId.num++

                $this.$emit("selected", checkedData)

            },
            /**
             * 下拉搜索
             */
            searchSelectData() {
                const $this = this

                const val = $this.searchDataState

                const isChecked = $this.listData.some((item) => {
                    return item.optState
                })

                if (isChecked) {
                    $this.listData.map((item) => {

                        item.optState = false

                    })
                }

                if (val) {

                    $this.check ? $this.selected = '请选择' : ''

                    $this.blurState = false

                    $this.checkSelectedAll(false, true)

                    $this.querySearchAsync(val)

                } else {

                    $this.check ? $this.selected = '全部' : ''

                    $this.blurState = true

                    $this.listData = $this.defaultListData

                    $this.checkSelectedAll(true, false)

                    $this.listData.map((item) => {

                        item.optState = true

                    })

                }

                $this.order = null
            },
            checkSelectedAll(all, single) {

                const $this = this

                $this.closeSingleChecked = single

                $this.checkedAll = all

            },
            automatismSlideOff(e) {

                const $this = this

                if (!($this.$el && $this.$el.contains(e.target))) $this.on = false

            },
            confirmChecked() {
                const $this = this

                const checkedData = $this.listData.filter((item) => {
                    return item.optState
                })

                $this.on = false

                $this.$emit('checkedData', checkedData)
            },
            initListData(obj) {
                const $this = this

                $this.emptyState = true

                if (obj.length <= 0) {

                    $this.listData = []

                    $this.selected = '全部'

                    return

                }

                obj.map((item) => {

                    item.assetState = true

                })

                $this.listData = obj

                $this.checkSelectedAll(false, true)

                if ($this.isDefault) {

                    $this.defaultCheckedVal()

                    return

                } else {

                    $this.selected = $this.defaultSelected ? $this.defaultSelected : obj[0].name

                    $this.isFirstNode ? $this.$emit("selected", obj[0]) : ''

                }

                if ($this.check) {

                    $this.selected = '请选择'

                    $this.defaultCheckedFilter(obj)

                }

            },
            followMouseCheckList(e) {
                const $this = this
                const keyCode = e.keyCode

                switch (keyCode) {
                    case 13: // 回车

                        var el = $($this.$refs.searchList).find('.active'), dataOrder = el.data('order')

                        var selectName = dataOrder >= 0 ? $this.listData[dataOrder].name : $this.defaultText

                        /**
                         * 回车搜索
                         */
                        if ($this.selected == selectName || $this.selected == $this.defaultText || $this.selected == '请选择') {

                            $this.searchSelectData()

                            el = null

                            return

                        }else {

                            if(!(dataOrder >= 0)) {//回车搜索为空恢复默认选中数据

                                $this.defaultListData.filter((item, index) => {

                                    if (item.name == $this.selected) {

                                        $this.setScrollDistance(index)

                                        $this.order = index

                                    }

                                })

                                $this.listData = $this.defaultListData

                                el = null

                                return

                            }

                        }

                        /**
                         * 上下键移动回车选中
                         */
                        if ($this.order >= 0) {

                            let num = $this.order === null ? el.data('order') : $this.order

                            $this.selected = $this.listData[num].name

                            $this.$emit("selected", $this.listData[num], $(el))

                        } else {

                            $this.order = -1

                            $this.selected = '全部'

                        }

                        $this.on = false

                        el = null

                        break
                    case 38: // 上行
                        if ($this.order <= 0) {

                            $this.order = -1

                            return

                        }

                        $this.order -= 1

                        $this.setScrollDistance($this.order)

                        break
                    case 40: // 下行
                        if ($this.order >= $this.listData.length-1) return

                        $this.order += 1

                        $this.setScrollDistance($this.order)

                        $($this.$refs.searchList).find('.active').removeClass('active')

                        break
                }

            },
            setScrollDistance(order) {
                const $this = this

                $this.$refs['vs'].scrollTo(
                    { y: order * 30 },
                    500,
                    'easeInQuad'
                )
            },
            querySearchAsync(queryString) {
                const $this = this
                const restaurants = $this.defaultListData

                $this.listData = queryString ? restaurants.filter($this.createStateFilter(queryString)) : restaurants

            },
            createStateFilter(queryString) {

                return (state) => {

                    return state.name && state.name.includes(queryString)

                }

            },
            defaultCheckedVal() {
                const $this = this
                let checkedVal = []

                $this.defaultListData.filter((item, index) => {

                    if ((item.id === $this.defaultSelected && item.id) || item.name === $this.defaultSelected && item.name) {

                        checkedVal = item

                        $this.order = index

                        if ($this.defaultSearch) $this.searchDataState = item.name

                    }

                })

                if (checkedVal.length <= 0) {

                    $this.searchDataState = ''

                    $this.check ? $this.defaultCheckedFilter($this.defaultListData) : $this.selected = $this.defaultText

                    $this.order = -1

                    return

                }

                $this.selected = checkedVal[0] ? checkedVal[0].name : checkedVal.name

            },
            /**
             * 默认选中赋值
             */
            defaultCheckedFilter(obj) {

                const $this = this

                if ($this.defaultSelected instanceof Array) {

                    let str = ''

                    obj.map(item => {

                        if ($this.defaultSelected.includes(item.id)) {

                            item.optState = true

                            item.assetState = true

                            str += `${item.name},`

                        }

                    })

                    $this.selected = str.substring(0, str.length - 1)

                } else {

                    obj.map((item) => {

                        $this.checkedAll ? item.optState = true : item.optState = false

                        item.assetState = true

                    })

                    $this.check ? $this.selected = '请选择' : $this.selected = '全部'

                }

            },
            /**
             * 选取插值过滤
             */
            insertSelectedFilter() {

                const $this = this

                let str = ''

                $this.listData.map((item) => {
                    if (item.optState) {
                        str += `${item.name},`
                    }
                })

                return str.substring(0, str.length - 1)

            },
            /**
             * 选中切换
             */
            changeChecked(obj) {

                const $this = this
                const parentEl = obj.hasClass('list') ? obj : obj.parent()
                const order = parentEl.data("order")
                let data = $this.listData

                $('.list').removeClass("active")

                data[order].optState = !data[order].optState

                const beforeChecked = $this.listData.filter((item) => {

                    return item.optState

                })

                if (beforeChecked.length > 50 && $this.checkCountLimit) {

                    if (!$this.blurState) {

                        data[order].optState = false

                        $this.toastMove()

                        return selectedObj

                    }

                }

                const noChecked = data.some( function( item ){ // 查询未选中的项

                    return !item.optState

                })

                if (!noChecked) {

                    $this.checkSelectedAll(true, false)

                } else {

                    if ($this.checkedAll) {

                        // data.map((item, index) => {
                        //
                        //     index !== parseInt(order) ? item.optState = false : item.optState = true
                        //
                        // })

                        $this.limitFullData = false

                        $this.checkSelectedAll(false, true)

                    }

                }

                $this.selected = $this.insertSelectedFilter()

                const selectedObj = $this.listData.filter((item) => {

                    return item.optState

                })

                if (selectedObj.length >= 50) {

                    $this.listData.map((item) => {

                        if (!item.optState) {

                            item.assetState = false

                        }

                    })

                }

                return selectedObj

            },
            /**
             * 选中的值
             * @param e
             */
            checked(id, e) {
                const $this = this
                const target = $(e.target)
                const parentEl = target.hasClass('list') ? target : target.parent()
                const index = parentEl.data("index")
                const order = parentEl.data("order")

                $this.id = id

                if ($this.check) {

                    if(id === 'all') {

                        if (!$this.blurState) {

                            let data = null

                            if ($this.checkCountLimit) {

                                data = $this.listData.slice(0, 50)

                                $this.listData.slice(50, $this.listData.length).map((item) => { item.optState = false })

                            }else {

                                data = $this.listData

                            }

                            $this.selected = ''

                            data.map((item, index) => {

                                if (item.optState) {

                                    $this.selected = '请选择'

                                } else {

                                    index <= 0 ? $this.selected = item.name : $this.selected += `,${item.name}`

                                }

                                $this.checkedAll ? item.optState = false : item.optState = true

                            })

                            $this.$emit("selected", data, target, index)

                        }

                        $this.checkSelectedAll(!$this.checkedAll, false)

                        return

                    }

                    const selectedObj = $this.changeChecked(target)

                    $this.$emit("selected", selectedObj, target, index)
                    // if ($this.listData[order].assetState) {
                    //
                    //     const selectedObj = $this.changeChecked(target)
                    //
                    //     $this.$emit("selected", selectedObj, target, index)
                    //
                    // } else {
                    //
                    //     $this.toastMove()
                    //
                    // }

                } else {

                    $this.on = false

                    //if (target.hasClass('active')) return

                    $this.order = order

                    $this.selected = target.text()

                    target.addClass("active")

                    target.siblings().removeClass("active")

                    if (!$this.closeSingleChecked) {

                        $this.closeSingleChecked = true

                    }

                    $this.listData.map((item, index) => {

                        item.optState = index === order

                    })

                    $this.$emit("selected", $this.listData[order], target, index)

                }

                $this.$emit("itemId", $this.id, index)

                $this.filterData(index, $this.listData)

            },
            /**
             * 下拉动画
             */
            slideDown() { // selectWall

                const $this = this

                $this.$emit("toggleSlide")

                $this.on ? ($this.on = false) : ($this.on = true)

            },
            // 过滤出下拉列表中的children
            filterData(index, arr) {
                const $this = this

                if (!arr) return

                arr.map(item => {

                    if (item.id === $this.id && $this.id !== "all") {

                        $this.$emit("children", index, item.children)

                    } else {

                        $this.filterData(index, item.children)

                    }
                })
            }
        },
        beforeDestroy () {

            document.removeEventListener('click', this.automatismSlideOff ,false)

        }
    };
</script>

<style scoped lang="stylus">
    .selectMask
        position: absolute
        top: 0
        left: 0
        right: 0
        bottom: 0
        z-index: 3
        background-color: rgba(0,0,0,.3)
    .footer
        position: absolute
        left: 0
        bottom: 0
        width: 100%
        text-align: right
        .el-button
            width: 100%
            margin: 0
            border-radius: 0
    .empty
        height: 48px
        line-height: 48px
        text-align: center
    .fa-square-o:before
        content: "\F096" !important
    .search
        position: relative
        .btn-reverse
            position: absolute
            right: 3px
            top: 2px
            display: block
            width: 40px
            height: 26px
            line-height: 26px
            font-size: 12px
            color: rgba(225, 225, 225, .8)
            cursor: pointer
            border: 1px solid #284689
            border-radius: 4px
            text-align: center
        .fa
            position: absolute
            top: 0
            right: 6px
            width: 30px
            height: 26px
            line-height: 26px
            font-size: 14px
            color: #fff
            text-align: center
            cursor: pointer
        &.reverse
            padding-right: 40px
            .fa
                right: 44px
    .search-panel
        width: 100%
        padding: 0 5px 5px
        box-sizing: border-box
        & > input
            width: 100%
            padding-right: 25px
            box-sizing: border-box
    .inputSelect
        position: absolute
        left: 0
        top: 0
        width: 80%
        border: none
        text-align: left
    >>> .__view
        width: 100% !important

    .slide-fade-enter-active, .slide-fade-leave-active
        transform: translateY(-10px)

    .slide-fade-enter, .slide-fade-leave-to
        transform: translateY(-10px)
        opacity: 0

    .continuePanel
        display: inline-block

    .dcimSelect
        position: relative
        display: inline-block
        width: 140px
        margin-right: 5px
        text-align: left
        vertical-align: middle

    .s-panel
        position: absolute
        top: 32px
        left: 0
        width: 100%
        padding: 5px 0
        border: 1px solid #284689
        background-color: #0B1531
        z-index: 3

    .list
        width: 100%
        min-height: 30px
        line-height: 30px
        padding: 0 15px
        color: #fff
        font-size: 14px
        cursor: pointer
        white-space: nowrap
        text-overflow: ellipsis
        overflow: hidden
        &:hover, &.active
            background-color: #296fee
        &:hover >>>.el-checkbox__inner, &.active >>>.el-checkbox__inner
            border-color: #fff
        &:last-child
            border-bottom: none

    .s-list
        position: relative
        min-height: 60px
        max-height: 324px
    .btn-handle
        padding-bottom: 30px
    .s-list .el-checkbox
        line-height: 0
        margin-top: -1px
        margin-right: 5px
        vertical-align: middle
    .s-header
        position: relative
        height: 30px
        line-height: 30px
        padding-left: 10px
        padding-right: 25px
        white-space: nowrap
        text-overflow: ellipsis
        color: #fff
        font-size: 14px
        cursor: pointer
        overflow: hidden
        border: 1px solid #284689
        .fa-box
            position: absolute
            right: 0px
            top: 0
            width: 30px
            height: 28px
            line-height: 28px
            text-align: center
            color: #284689
            font-size: 20px
            cursor: pointer
</style>
